package com.steel.yfmall.cloud.assistant.view.impl;

import com.alibaba.fastjson.JSONObject;
import com.steel.yfmall.cloud.assistant.utils.zg.ZgViewUtil;
import com.steel.yfmall.cloud.assistant.view.UsageCodeBeanService;
import com.steel.yfmall.cloud.assistant.zg.ZgSOService;
import com.steel.yfmall.cloud.assistant.dto.zg.SynZgResult;
import com.steel.yfmall.cloud.assistant.dto.zg.ZgSOResultBean;
import com.steel.yfmall.cloud.assistant.dto.zg.ZgViewBean;
import com.steel.yfmall.cloud.assistant.po.view.UsageCodeBean;
import com.steel.yfmall.cloud.assistant.po.view.UsageCodeBeanExample;
import com.steel.yfmall.cloud.assistant.view.mapper.UsageCodeBeanMapper;
import com.steel.yfmall.cloud.components.utils.base.APIMsgBean;
import com.steel.yfmall.cloud.components.utils.base.ResponseCode;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.*;

/**
 * 用途码信息接口实现类
 *
 * @Author luo deng ren
 * @Date 2020-11--10 20:18:36
 **/
@Service("usageCodeBeanService")
@Slf4j
public class UsageCodeBeanServiceImpl implements UsageCodeBeanService {
    @Resource
    UsageCodeBeanMapper usageCodeBeanMapper;

    @Resource
    ZgSOService zgSOService;

    /**
     * sql拼接
     *
     * @param criteria      sql拼接
     * @param usageCodeBean 参数
     */
    private void getSearchData(UsageCodeBeanExample.Criteria criteria, UsageCodeBean usageCodeBean) {
        // ID
        if (usageCodeBean.getId() != null && usageCodeBean.getId() > 0) {
            criteria.andIdEqualTo(usageCodeBean.getId());
        }
        // 产品规范代码
        if (StringUtils.isNotBlank(usageCodeBean.getPsrNo())) {
            criteria.andPsrNoEqualTo(usageCodeBean.getPsrNo());
        }
        //用途码
        if (StringUtils.isNotBlank(usageCodeBean.getApnNo())) {
            criteria.andApnNoEqualTo(usageCodeBean.getApnNo());
        }

        //用途描述
        if (StringUtils.isNotBlank(usageCodeBean.getApnDesc())) {
            criteria.andApnDescEqualTo(usageCodeBean.getApnDesc());
        }
        //创建时间
        if (usageCodeBean.getCreateTime() != null) {
            criteria.andCreateTimeEqualTo(usageCodeBean.getCreateTime());
        }
        //版本号
        if (usageCodeBean.getVersionInt() != null && usageCodeBean.getVersionInt() > 0) {
            criteria.andVersionIntEqualTo(usageCodeBean.getVersionInt());
        }
        //修改时间
        if (usageCodeBean.getUpdateTime() != null) {
            criteria.andUpdateTimeEqualTo(usageCodeBean.getUpdateTime());
        }
    }

    /**
     * 中冠视图请求的参数校验
     *
     * @param zgViewBean 视图名称
     * @return 校验结果
     */
    private String checkData(ZgViewBean zgViewBean) {
        String msg = "";
        if (!StringUtils.isNotBlank(zgViewBean.getMethod())) {
            msg += "请求方法不能为空";
        }
        if (!StringUtils.isNotBlank(zgViewBean.getViewId())) {
            msg += "请求的视图不能为空";
        }
        if (!StringUtils.isNotBlank(zgViewBean.getPageNum())) {
            msg += "请求的页码不能为空";
        }
        return msg;
    }

    @Override
    public APIMsgBean synchronizationZgUsageCodeBean(ZgViewBean zgViewBean) {
        APIMsgBean serviceDataBean = new APIMsgBean();
        //默认失败
        serviceDataBean.setSoaStateBean(ResponseCode.buildEnumErrorSOAStateBean("数据同步失败"));
        //参数校验
        String msg = checkData(zgViewBean);
        if (!StringUtils.isBlank(msg)) {
            serviceDataBean.setSoaStateBean(ResponseCode.buildEnumErrorSOAStateBean(msg));
            return serviceDataBean;
        }

        SynZgResult synZgResult = new SynZgResult();
        //同步计时开始
        long beginTime = System.currentTimeMillis();
        ZgSOResultBean viewData = zgSOService.getViewData(zgViewBean);
        //同步计时结束
        long endTime = System.currentTimeMillis();
        long costTime = (endTime - beginTime);
        //请求中冠成功后
        if ("Y".equals(viewData.getIsSuccess())) {
            List<UsageCodeBean> usageCodeBeans = null;
            try {
                usageCodeBeans = JSONObject.parseArray(viewData.getData(), UsageCodeBean.class);
            } catch (Exception e) {
                serviceDataBean.setSoaStateBean(ResponseCode.buildEnumErrorSOAStateBean("用途码信息数据同步解析出错"));
                log.error("用途码信息数据同步解析出错，错误信息：", e);
            }
            //检查数据库是否有重复,过滤掉重复信息并设置创建、更新、版本信息
            usageCodeBeans = checkDataBase(usageCodeBeans);
            if (!CollectionUtils.isEmpty(usageCodeBeans)) {
                //批量新增
                int i = usageCodeBeanMapper.batchInsertByList(usageCodeBeans);
                if (i > 0) {
                    //设置同步所用时间
                    synZgResult.setSynTime(String.valueOf(costTime));
                    //设置同步条数
                    synZgResult.setCountNum(i);
                    //设置同步状态
                    synZgResult.setState(true);
                    serviceDataBean.setSoaStateBean(ResponseCode.buildEnumSuccessSOAStateBean("数据同步成功"));
                    serviceDataBean.setData(synZgResult);
                    //日志记录
                    log.info("用途码信息数据同步成功，本次同步" + i + "条数据,耗时" + costTime + "毫秒");
                }
            } else {
                log.info("无数据同步");
                serviceDataBean.setSoaStateBean(ResponseCode.buildEnumErrorSOAStateBean("无数据同步"));
            }
        } else {
            serviceDataBean.setSoaStateBean(ResponseCode.buildEnumErrorSOAStateBean(viewData.getMsg()));
        }
        //递归同步
        try {
            //起始页
            int startPage = Integer.parseInt(zgViewBean.getPageNum());
            //判断是否还有数据
            if (startPage < viewData.getZgpageData().getPages()) {
                startPage++;
                zgViewBean.setPageNum(String.valueOf(startPage));
                synchronizationZgUsageCodeBean(zgViewBean);
            }
        } catch (Exception e) {
            serviceDataBean.setSoaStateBean(ResponseCode.buildEnumErrorSOAStateBean("用途码信息数据递归同步出错"));
            log.error("用途码信息数据递归同步出错，错误信息：", e);
        }
        return serviceDataBean;
    }

    /**
     * 检查数据库中数据是否存在，将不存在的数据返回，过滤掉重复的数据
     *
     * @param usageCodeBeans 需要检查的数据
     * @return List<ReceivingGoodsBean> 过滤剩余的数据
     */

    public List<UsageCodeBean> checkDataBase(List<UsageCodeBean> usageCodeBeans) {
        if (CollectionUtils.isEmpty(usageCodeBeans)) {
            return null;
        }
        UsageCodeBeanExample usageCodeBeanExample = new UsageCodeBeanExample();
        UsageCodeBeanExample.Criteria criteria = usageCodeBeanExample.createCriteria();
        Map<String, UsageCodeBean> usageCodeBeanMap = new HashMap<>();
        for (UsageCodeBean usageCodeBean : usageCodeBeans) {
            String onlyKey = usageCodeBean.getPsrNo() + "," + usageCodeBean.getApnNo();
            usageCodeBeanMap.put(onlyKey, usageCodeBean);
        }
        //查询数据库是否有重复数据
        ArrayList<String> keys = new ArrayList<>(usageCodeBeanMap.keySet());
        List<String> psrNoList = new ArrayList<>();
        List<String> apnNoList = new ArrayList<>();
        for (String key : keys) {
            String[] split = key.split(",");
            psrNoList.add(split[0]);
            apnNoList.add(split[1]);
        }
        criteria.andPsrNoIn(psrNoList);
        criteria.andApnNoIn(apnNoList);
        List<UsageCodeBean> usageCodeBeans1 = usageCodeBeanMapper.selectByExample(usageCodeBeanExample);
        List<UsageCodeBean> oldUsageCodeBean = new ArrayList<>();
        for (UsageCodeBean usageCodeBean : usageCodeBeans1) {
            String dbKey = usageCodeBean.getPsrNo() + "," + usageCodeBean.getApnNo();
            if (usageCodeBeanMap.containsKey(dbKey)) {
                oldUsageCodeBean.add(usageCodeBeanMap.get(dbKey));
                usageCodeBeanMap.remove(dbKey);
            }
        }
        usageCodeBeans = new ArrayList<>(usageCodeBeanMap.values());
        for (int i = 0; i < usageCodeBeans.size(); i++) {
            usageCodeBeans.get(i).setCreateTime(new Date());
            usageCodeBeans.get(i).setUpdateTime(new Date());
            usageCodeBeans.get(i).setVersionInt(0);
        }
        //当存在重复数据时
        if (!CollectionUtils.isEmpty(oldUsageCodeBean)) {
            //复用对象
            usageCodeBeanMap.clear();
            for (UsageCodeBean usageCodeBean : oldUsageCodeBean) {
                String dbKey = usageCodeBean.getPsrNo() + "," + usageCodeBean.getApnNo();
                usageCodeBeanMap.put(dbKey, usageCodeBean);
            }
            //细致比对取出差异数据然后线程修改
            List<UsageCodeBean> usageCodeBeanList = equalsDataChange(usageCodeBeanMap);
            if (!CollectionUtils.isEmpty(usageCodeBeanList)) {
                AsynchronousUpDate asynchronousUpDate = new AsynchronousUpDate(usageCodeBeanList);
                new Thread(asynchronousUpDate).start();
            }
        }
        return usageCodeBeans;
    }

    /**
     * @param usageCodeBeanMap 重复的数据
     * @return List<ReachRegionBean> 重复且有差异的信息
     * @Description 校验比较返回重复且有差异的的信息
     */
    private List<UsageCodeBean> equalsDataChange(Map<String, UsageCodeBean> usageCodeBeanMap) {
        if (usageCodeBeanMap.isEmpty()) {
            return null;
        }
        UsageCodeBeanExample usageCodeBeanExample = new UsageCodeBeanExample();
        UsageCodeBeanExample.Criteria criteria = usageCodeBeanExample.createCriteria();
        ArrayList<String> keys = new ArrayList<>(usageCodeBeanMap.keySet());
        List<String> psrNoList = new ArrayList<>();
        List<String> apnNoList = new ArrayList<>();
        for (String key : keys) {
            String[] split = key.split(",");
            psrNoList.add(split[0]);
            apnNoList.add(split[1]);
        }
        criteria.andPsrNoIn(psrNoList);
        criteria.andApnNoIn(apnNoList);
        List<UsageCodeBean> usageCodeBeans = usageCodeBeanMapper.selectByExample(usageCodeBeanExample);
        List<UsageCodeBean> usageCodeBeanList = new ArrayList<>();
        for (UsageCodeBean usageCodeBean : usageCodeBeans) {
            String dbKey = usageCodeBean.getPsrNo() + "," + usageCodeBean.getApnNo();
            if (usageCodeBeanMap.containsKey(dbKey)) {
                UsageCodeBean usageCodeBean1 = usageCodeBeanMap.get(dbKey);
                if (!usageCodeBean1.getPsrNo().equals(usageCodeBean.getPsrNo())
                        || !usageCodeBean1.getApnNo().equals(usageCodeBean.getApnNo())) {
                    usageCodeBean1.setId(usageCodeBean.getId());
                    usageCodeBean1.setUpdateTime(new Date());
                    usageCodeBean1.setVersionInt(usageCodeBean.getVersionInt() + 1);
                    usageCodeBeanList.add(usageCodeBean1);
                }
            }
        }
        return usageCodeBeanList;
    }

    private class AsynchronousUpDate implements Runnable {
        List<UsageCodeBean> usageCodeBeans;

        public AsynchronousUpDate(List<UsageCodeBean> usageCodeBeans) {
            this.usageCodeBeans = usageCodeBeans;
        }

        @Override
        public void run() {
            try {
                if (!CollectionUtils.isEmpty(usageCodeBeans)) {
                    //记录总需改数据
                    int i = 0;
                    long beginTime = System.currentTimeMillis();
                    for (UsageCodeBean usageCodeBean : usageCodeBeans) {
                        i += usageCodeBeanMapper.updateByPrimaryKeySelective(usageCodeBean);
                    }
                    long endTime = System.currentTimeMillis();
                    long costTime = (endTime - beginTime);
                    log.info("异步修改用途码信息成功，本次修改" + i + "条数据，耗时" + costTime + "毫秒");
                }
            } catch (Exception e) {
                log.error("同步后的差异数据修改失败，错误原因：", e);
            }
        }
    }
}
